﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using TFDP.Common;
using System.ComponentModel;

namespace TFDP.VsPackage.Forms
{
    /// <summary>
    /// Interaction logic for QueueMonitorContent.xaml
    /// </summary>
    public partial class QueueMonitorContent : UserControl
    {
        private BindingList<IProcessor> processors;
        private Action<IProcessor> updateAction;
        private Action<IProcessor> projectClosedAction;
        private Action clearAction;

        public BindingList<IProcessor> Processors
        {
            get { return processors; }
        }

        public IProcessor SelectedProcessor
        {
            get { return processorSelector.SelectedItem as IProcessor; }
        }

        public QueueMonitorContent()
        {
            this.processors = new BindingList<IProcessor>();

            this.updateAction = (p) =>
            {
                UpdateCore(p);
            };
            this.projectClosedAction = (p) =>
            {
                ProjectClosed(p);
            };
            this.clearAction = () =>
            {
                ClearCore();
            };

            InitializeComponent();
        }

        internal void QueueChanged(IProcessor processor)
        {
            if (processor == null)
                throw new ArgumentNullException("processor");
       
            if (!this.Dispatcher.CheckAccess())
            {
                this.Dispatcher.BeginInvoke(updateAction, processor);

                return;
            }
            else
            {
                updateAction(processor);
            }
        }

        internal void ProjectClosed(IProcessor processor)
        {
            if (processor == null)
                throw new ArgumentNullException("processor");

            if (!this.Dispatcher.CheckAccess())
            {
                this.Dispatcher.BeginInvoke(updateAction, processor);

                return;
            }
            else
            {
                processors.Remove(processor);
                clearAction();
            }
        }

        private void UpdateCore(IProcessor processor)
        {
            if (processor == null)
            {
                throw new ArgumentNullException("processor");
            }

            if (!processors.Contains(processor))
            {
                processors.Add(processor);
            }

            if(processorSelector.SelectedItem != processor)
            {
                processorSelector.SelectedItem = processor;
            }

            List<Microsoft.Data.Schema.SchemaModel.IModelElement> list = null;

            list = processor.Queue.ToList();
                
            var items = list
                .Select(item => new { Name = item.GetFullName(), Type = processor.GetTypeName(item) });

            queuedItems.ItemsSource = items.ToList();
        }

        private void ClearCore()
        {
            queuedItems.ItemsSource = null;
        }

        private void processorSelector_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            IProcessor selected = processorSelector.SelectedItem as IProcessor;

            if (selected != null)
            {
                updateAction(selected);
            }
            else
            {
                clearAction();
            }
        }

        private void startButton_Click(object sender, RoutedEventArgs e)
        {
            if (SelectedProcessor != null)
                SelectedProcessor.Start();
        }

        private void stopButton_Click(object sender, RoutedEventArgs e)
        {
            if (SelectedProcessor != null)
                SelectedProcessor.Stop();
        }

        private delegate void VoidDelegate();

        private void clearButton_Click(object sender, RoutedEventArgs e)
        {
            if (SelectedProcessor != null)
            {
                SelectedProcessor.Queue.Clear();
                updateAction(SelectedProcessor);
            }
        }
    }
}
